#include "stdafx.h"
#include "UIElement.h"

namespace DirectUI
{
	CUIElement::CUIElement(void)
		: m_rcElement(0, 0, 0, 0)
	{
		ProperyInfoInit();
		GetProperty(Opacity)->SetDoubleValue(1.0);
		GetProperty(Background)->SetColorValue(0);
		GetProperty(HorizontalAlignment)->SetAlignValue(UIAlign_Near);
		GetProperty(VerticalAlignment)->SetAlignValue(UIAlign_Near);


		m_bMouseIn = false;
	}


	CUIElement::~CUIElement(void)
	{
	}


	IUIElement* CUIElement::GetTopPage() 
	{ 
		if ( m_spTopPage )
			return m_spTopPage;
		if ( !IsTopPage() ) 
		{
			assert(FALSE);
			return NULL;
		}
		return this;
	}


	BOOL CUIElement::IsTopPage()
	{
		CUIObjectQIPtr<IUIPage> sp(this);
		if ( !sp || !sp->GetCoreWindow() )
		{
			assert(FALSE);
			return FALSE;
		}
		return TRUE;
	}

	void CUIElement::ParseAttribute(LPCTSTR lpszAttr)
	{
		xml_document doc;
		if ( !doc.load(lpszAttr) )
			return;

		xml_node node = doc.first_child();
		OnBeforeParseAttribute(node);

		xml_node::attribute_iterator it = node.attributes_begin();
		while ( it != node.attributes_end() )
		{
			xml_attribute attr = *it;
			OnParseAttribute(attr);
			++it;
		}
	}


	void CUIElement::OnBeforeParseAttribute(xml_node& node)
	{

	}


	void CUIElement::OnParseAttribute(xml_attribute& attr)
	{
		CString szAttrName = attr.name();
		CUIObjectPtr<IUIProperty> spProperty = GetProperty(szAttrName);
		if ( !spProperty )
			return;
		CUIProperty::ParseAttribute(attr, spProperty);
	}

	void CUIElement::OnDraw(HDC hDC, IUIRender* lpRender)
	{
		Gdiplus::Color clr = GetProperty(Background)->GetColorValue();
		if ( clr.GetAlpha() != 0 )
		{
			CRect rc = m_rcElement;
			lpRender->FillRect(hDC, rc, GetProperty(Background)->GetColorValue());
		}
	}


	void CUIElement::PropertyChanged(int PropertyNameEnum)
	{
		if ( !m_spTopPage )
			return;

		switch (PropertyNameEnum)
		{
		case Opacity:
		case Background:
			Invalidate();
			break;

		default:
			break;
		}
	}

	BOOL CUIElement::AddChildElement( IUIElement* lpElement )
	{
		lpElement->SetParent(this);
		m_vSubElements.push_back(lpElement);
		CString szName = lpElement->GetProperty(Name)->GetStringValue();
		szName.Trim(), szName.MakeLower();
		if ( !szName.IsEmpty() )
		{
#ifdef DEBUG
			assert(m_mapSubElements.find(szName)==m_mapSubElements.end());
#endif
			m_mapSubElements[szName] = lpElement;
		}
		return TRUE;
	}

	IUIElement* CUIElement::FindElementByName( LPCTSTR lpszName )
	{
		CString szName = lpszName;
		szName.Trim(), szName.MakeLower();
		if ( !szName.IsEmpty() )
		{
			CUIControlTemplate* pControlTemplate = GetControlTemplate(this);
			if ( pControlTemplate )
			{
				for ( unsigned int i = 0; i < pControlTemplate->m_vControlTemplateElements.size(); i++ )
				{
					IUIElement* p = pControlTemplate->m_vControlTemplateElements[i];
					CString szName1 = p->GetProperty(Name)->GetStringValue();
					if ( szName1.CollateNoCase(szName) == 0 )
						return p;

					CUIObjectPtr<IUIElement> spElement = p->FindElementByName(lpszName);
					if ( spElement )
						return spElement;
				}
			}

			std::map<CString, CUIObjectPtr<IUIElement>>::iterator pit = m_mapSubElements.find(szName);
			if ( pit != m_mapSubElements.end() )
			{
				return pit->second;
			}
			else
			{
				std::vector<CUIObjectPtr<IUIElement>>::iterator pit = m_vSubElements.begin();
				for ( ; pit != m_vSubElements.end(); ++pit )
				{
					CUIObjectPtr<IUIElement> spElement = (*pit)->FindElementByName(lpszName);
					if ( spElement )
						return spElement;
				}
			}
		}
		return NULL;
	}

	HRESULT CUIElement::QueryInterface( const GUID& guid, void** lppObject )
	{
		if ( guid == __uuidof(IUIElement) )
		{
			if (lppObject)
			{
				*lppObject = (IUIElement*)this;
				AddRef();
			}
			return S_OK;
		}
		else if ( guid == __uuidof(IUIPropertyEvent) )
		{
			if (lppObject)
			{
				*lppObject = (IUIPropertyEvent*)this;
				AddRef();
			}
			return S_OK;
		}

		return __super::QueryInterface(guid, lppObject);
	}

	CUIControlTemplate* CUIElement::GetControlTemplate( IUIElement* lpElement )
	{
		CUIElement* pDrawElement = (CUIElement*)lpElement;
		if ( pDrawElement->m_spControlTemplate )
			return (CUIControlTemplate*)(IUIControlTemplate*)pDrawElement->m_spControlTemplate;
		return NULL;
	}

	void CUIElement::GotoState( LPCTSTR lpszState )
	{
		std::map<CString, CUIObjectPtr<IUIVisualStateGroup>>::iterator pit = m_vVisualStateGroups.begin();
		for ( ; pit != m_vVisualStateGroups.end(); ++pit )
		{
			CUIVisualStateGroup* pGroup = (CUIVisualStateGroup*)(IUIVisualStateGroup*)pit->second;
			if ( pGroup )
			{
				pGroup->GotoState(this, lpszState);
			}
		}
	}

	void CUIElement::Invalidate()
	{
		CUIObjectQIPtr<IUIPage> spPage = GetTopPage();
		if ( spPage &&spPage->GetCoreWindow() )
			spPage->GetCoreWindow()->InvalidateRect(m_rcElement);
	}

	bool CUIElement::IsVisiable()
	{
		return true;
	}

	void CUIElement::PreviewMouseMove( IMouseEventArgs* lpArgs )
	{

	}

	void CUIElement::MouseMove( IMouseEventArgs* lpArgs )
	{

	}

	void CUIElement::PreviewLButtonDown( IMouseEventArgs* lpArgs )
	{

	}

	void CUIElement::LButtonDown( IMouseEventArgs* lpArgs )
	{

	}

	void CUIElement::PreviewLButtonUp( IMouseEventArgs* lpArgs )
	{

	}

	void CUIElement::LButtonUp( IMouseEventArgs* lpArgs )
	{

	}

	void CUIElement::MouseEnter( IMouseEventArgs* lpArgs )
	{

	}

	void CUIElement::MouseLeave( IMouseEventArgs* lpArgs )
	{

	}

}